package spring.context;

import spring.beans.BeanFactoryAware;
import spring.beans.factory.BeanDefinitionRegistry;
import spring.beans.factory.DefaultListableBeanFactory;

/**
 * 启动模板类
 */
public abstract class AbstractApplicationContext extends DefaultListableBeanFactory implements ApplicationContext {

    // 注册表
    protected BeanDefinitionRegistry registry = new DefaultListableBeanFactory();

    // 线程锁
    final Object startShutdownMonitor = new Object();


    /**
     * Spring启动模板
     */
    public void refresh() {

//        synchronized (this.startShutdownMonitor) {

            prepareRefresh();

            // 获得BeanFactory
            DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) registry;

            prepareBeanFactory(beanFactory);

            try {

                invokeBeanFactoryPostProcessors(beanFactory);

                registerBeanPostProcessors(beanFactory);

                finishBeanFactoryInitialization(beanFactory);


            } catch (Exception e) {
                e.printStackTrace();
            }

//        }


    }

    /**
     * 调用一切实现了ImportBeanDefinitionRegistrar接口的注册方法
     * @param beanFactory
     */
    private void invokeBeanFactoryPostProcessors(DefaultListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory);
    }

    @Override
    public Object getBean(String beanName) {
        return ((DefaultListableBeanFactory) registry).getBean(beanName);
    }


    /**
     * 核心目的：通过Spring的beanFactory创建单例(懒加载)
     * 1、注册BeanDefinition 2、准备BeanPostProcessor
     */
    private void finishBeanFactoryInitialization(DefaultListableBeanFactory beanFactory) {
        beanFactory.preInstantiateSingletons();
    }

    /**
     * 注册BeanPostProcessors
     * @param beanFactory
     */
    private void registerBeanPostProcessors(DefaultListableBeanFactory beanFactory){
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory);
    }

    /**
     * 给工厂设置以下参数
     * 这里传的是当前环境的类加载器
     */
    protected void prepareBeanFactory(DefaultListableBeanFactory beanFactory) {
//        beanFactory.setLoader(ClassLoaderUtil.getClassLoader());
    }

    private void prepareRefresh() {
        System.out.println("Spring-mini starting...");
    }

}
